package com.example.drive.net

import android.os.Handler
import android.os.Looper
import android.util.Log
import com.example.drive.BuildConfig
import com.example.drive.net.callback.NetworkCallback
import com.example.drive.net.interceptor.CommonInterceptor
import com.example.drive.net.request.OkHttpRequest
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import java.io.IOException
import java.util.concurrent.TimeUnit

const val TAG = "OkHttpHelper"

val okHttpClient: OkHttpClient by lazy {
    val builder = OkHttpClient.Builder()
    val loggingInterceptor = HttpLoggingInterceptor {
        Log.i(TAG, it)
    }
    loggingInterceptor.level =
        if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.BASIC
    builder.addInterceptor(CommonInterceptor())
        .addInterceptor(loggingInterceptor)
        .connectTimeout(12, TimeUnit.SECONDS)
        .readTimeout(12, TimeUnit.SECONDS)
        .writeTimeout(12, TimeUnit.SECONDS)
        .followRedirects(true)
        .retryOnConnectionFailure(true)
//        .sslSocketFactory()
    builder.build()
}

private val handler by lazy {
    Handler(Looper.getMainLooper())
}

fun Runnable.runOnUiThread() {
    handler.post(this)
}

/**
 * 发起异步请求
 */
fun <T> OkHttpRequest.asyncRequest(networkCallback: NetworkCallback<T>) {
    val responseCallback = object : Callback {
        override fun onResponse(call: Call, response: Response) {
            if (call.isCanceled()) {
                return
            }
            if (response.isSuccessful) {
                val data: T? = networkCallback.parseNetworkResponse(response)
                // 在主线程回调,可以直接更新UI
                Runnable {
                    networkCallback.onResponse(data)
                }.runOnUiThread()
            } else {
                Log.w(
                    TAG,
                    "Response is not successful,code = ${response.code},message = ${response.message}"
                )
            }
            response.close()
        }

        override fun onFailure(call: Call, e: IOException) {
            if (call.isCanceled()) {
                return
            }
            // 在主线程回调,可以直接更新UI
            Runnable {
                networkCallback.onFailure(e)
            }.runOnUiThread()
        }
    }
    okHttpClient.newCall(createRequest()).enqueue(responseCallback)
}

/**
 * 根据tag取消请求
 *
 * @param tag 指定的tag
 */
fun cancelRequestByTag(tag: Any) {
    val dispatcher = okHttpClient.dispatcher
    dispatcher.queuedCalls().forEach {
        it.takeIf {
            tag == it.request().tag()
        }?.cancel()
    }
    dispatcher.runningCalls().forEach {
        it.takeIf {
            tag == it.request().tag()
        }?.cancel()
    }
}

/**
 * 取消所有请求
 */
fun cancelAllRequest() {
    val dispatcher = okHttpClient.dispatcher
    dispatcher.queuedCalls().forEach {
        it.cancel()
    }
    dispatcher.runningCalls().forEach {
        it.cancel()
    }
}